//
//  UIImage+AFF.m
//  AnyfishApp
//
//  Created by Bob Lee on 15/9/6.
//  Copyright (c) 2015年 Anyfish. All rights reserved.
//

#import "UIImage+AFF.h"


#define FileHashDefaultChunkSizeForReadingData 1024*8
#define YY_FOUR_CC(c1,c2,c3,c4) ((uint32_t)(((c4) << 24) | ((c3) << 16) | ((c2) << 8) | (c1)))
#define YY_TWO_CC(c1,c2) ((uint16_t)(((c2) << 8) | (c1)))


#define kEdgeInset_InComming_Default      UIEdgeInsetsMake(17.0f, 21.0f, 13.0f, 17.0f)
#define kEdgeInset_OutGoing_Default       UIEdgeInsetsMake(17.0f, 17.0f, 13.0f, 21.0f)


#define kEdgeInset_Poolx_Default          UIEdgeInsetsMake(17.0f, 17.0f, 13.0f, 17.0f)

/**************  气泡命名参数，下载资源时要统一使用 ***************/
#define kBubble_Image_Name_Outgoint         @"outgoing"
#define kBubble_Image_Name_Incoming         @"incoming"
#define kBubble_Image_Name_Flat             @"flat"
#define kBubble_Image_Name_Select           @"-sel"
#define kBubble_Image_Name_Format           @"bubble-%@-%@-%@%@"

@implementation UIImage (AFF)


/**
*  根据图片名返回一张能够自由拉伸的图片 (从中间拉伸)
*/
+ (UIImage *)mh_resizableImage:(NSString *)imgName
{
    UIImage *image = [UIImage imageNamed:imgName];
    return [self mh_resizableImage:imgName capInsets:UIEdgeInsetsMake(image.size.height *.5f, image.size.width*.5f, image.size.height*.5f, image.size.width*.5f)];
}

+ (UIImage *)mh_resizableImage:(NSString *)imgName capInsets:(UIEdgeInsets)capInsets
{
    UIImage *image = [UIImage imageNamed:imgName];
    return [image resizableImageWithCapInsets:capInsets];
}

+ (UIImage *)mh_imageAlwaysShowOriginalImageWithImageName:(NSString *)imageName
{
    UIImage *image = [UIImage imageNamed:imageName];
    if ([image respondsToSelector:@selector(imageWithRenderingMode:)])
    {   //iOS 7.0+
        return [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }else{
        return image;
    }
}

+ (UIImage*)mh_thumbnailImageForVideo:(NSURL *)videoURL atTime:(NSTimeInterval)time {
    
//    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
//    NSParameterAssert(asset);
//    AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:asset];
//    assetImageGenerator.appliesPreferredTrackTransform = YES;
//    assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
//
//    CGImageRef thumbnailImageRef = NULL;
//    CFTimeInterval thumbnailImageTime = time;
//    NSError *thumbnailImageGenerationError = nil;
//    thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60)actualTime:NULL error:&thumbnailImageGenerationError];
//
//    if(!thumbnailImageRef)
//        NSLog(@"thumbnailImageGenerationError %@",thumbnailImageGenerationError);
//
//    UIImage*thumbnailImage = thumbnailImageRef ? [[UIImage alloc]initWithCGImage: thumbnailImageRef] : nil;
//
//    return thumbnailImage;
    return nil;
}

/// 获取屏幕截图
///
/// @return 屏幕截图图像
+ (UIImage *)mh_screenShot {
    // 1. 获取到窗口
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    
    // 2. 开始上下文
    UIGraphicsBeginImageContextWithOptions(window.bounds.size, YES, 0);
    
    // 3. 将 window 中的内容绘制输出到当前上下文
    [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:NO];
    
    // 4. 获取图片
    UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
    
    // 5. 关闭上下文
    UIGraphicsEndImageContext();
    
    return screenShot;
}


+ (UIImage *)getCornerImageFromImage:(UIImage *)image containerFrame:(CGRect)frame withRadious:(CGFloat)corner{
    return [self getCornerImageFromImage:image containerFrame:frame withRadious:corner cornerMask:UIHelperImageRadiusTopRight|UIHelperImageRadiusTopLeft|UIHelperImageRadiusBottomRight|UIHelperImageRadiusBottomLeft];
}

+ (UIImage *)getCornerImageFromImage:(UIImage *)image containerFrame:(CGRect)frame withRadious:(CGFloat)corner cornerMask:(UIHelperImageRadius)cornerMask{
    if(corner == 0.0f)
        return image;
    
    if( image != nil) {
        CGFloat imageWidth = image.size.width;
        CGFloat imageHeight = image.size.height;
        
        
        const CGFloat scale = [UIScreen mainScreen].scale;
        
        
        CGFloat imageAspectRatio = imageWidth/imageHeight;
        CGFloat containerAspectRatio = frame.size.width/frame.size.height;
        
        if (imageAspectRatio == containerAspectRatio)
        {
        }
        else
        {
            if (imageAspectRatio > containerAspectRatio)
            {
                imageWidth = imageHeight*containerAspectRatio;
            }
            else if (imageAspectRatio<containerAspectRatio)
            {
                imageHeight = imageWidth/containerAspectRatio;
            }
            
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(imageWidth, imageHeight), NO, scale);
            
            [image drawInRect:CGRectMake(0, 0, imageWidth, imageHeight)];
            image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
        }
        
        
        CGRect rect = CGRectMake(0.0f, 0.0f, imageWidth, imageHeight);
        
        corner = corner*imageHeight/frame.size.height;
        
        
        
        UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        CGContextBeginPath(context);
        CGContextSaveGState(context);
        CGContextTranslateCTM (context, 0, 0);
        CGContextScaleCTM (context, scale, scale);
        
        CGFloat rectWidth = CGRectGetWidth (rect)/scale;
        CGFloat rectHeight = CGRectGetHeight (rect)/scale;
        
        corner = corner/scale;
        
        
        CGContextMoveToPoint(context, 0.0f, rectHeight/2.0f);
        //左上圆角
        if (cornerMask&UIHelperImageRadiusTopLeft)
        {
            CGContextAddArcToPoint(context, 0.0f, 0.0f, rectWidth/2.0f, 0.0f, corner);
        }
        else
        {
            CGContextAddLineToPoint(context, 0.0f, 0.0f);
            CGContextAddLineToPoint(context, rectWidth/2.0f, 0.0f);
        }
        //右上圆角
        if (cornerMask&UIHelperImageRadiusTopRight)
        {
            CGContextAddArcToPoint(context, rectWidth, 0.0f, rectWidth, rectHeight/2.0f, corner);
        }
        else
        {
            CGContextAddLineToPoint(context, rectWidth, 0.0f);
            CGContextAddLineToPoint(context, rectWidth, rectHeight/2.0f);
        }
        //右下圆角
        if (cornerMask&UIHelperImageRadiusBottomRight)
        {
            CGContextAddArcToPoint(context, rectWidth, rectHeight, rectWidth/2.0f, rectHeight, corner);
        }
        else
        {
            CGContextAddLineToPoint(context, rectWidth, rectHeight);
            CGContextAddLineToPoint(context, rectWidth/2.0f, rectHeight);
        }
        //左下圆角
        if (cornerMask&UIHelperImageRadiusBottomLeft)
        {
            CGContextAddArcToPoint(context, 0, rectHeight, 0, rectHeight/2.0f, corner);
        }
        else
        {
            CGContextAddLineToPoint(context, 0, rectHeight);
            CGContextAddLineToPoint(context, 0, rectHeight/2.0f);
        }
        
        
        CGContextRestoreGState(context);
        CGContextClosePath(context);
        CGContextClip(context);
        
        [image drawInRect:CGRectMake(0.0f, 0.0f, imageWidth, imageHeight)];
        
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        
        return newImage;
    }
    
    return nil;
}

- (UIImage *)cutToCircle:(BOOL)clipToCircle
             withDiamter:(CGFloat)diameter
             borderColor:(UIColor *)borderColor
             borderWidth:(CGFloat)borderWidth
            shadowOffSet:(CGSize)shadowOffset
{
    if(diameter==0){
        diameter = self.size.height>self.size.width?self.size.width:self.size.height;
    }
    
    // increase given size for border and shadow
    CGFloat increase = diameter * 0.15f;
    CGFloat newSize = diameter + increase;
    
    CGRect newRect = CGRectMake(0.0f,
                                0.0f,
                                diameter,
                                diameter);
    
    // fit image inside border and shadow
    CGRect imgRect = CGRectMake(borderWidth,
                                borderWidth,
                                newRect.size.width-2*borderWidth,
                                newRect.size.height-2*borderWidth);
    
    UIGraphicsBeginImageContextWithOptions(newRect.size, NO, [UIScreen mainScreen].scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    
    // draw shadow
    if(!CGSizeEqualToSize(shadowOffset, CGSizeZero))
        CGContextSetShadowWithColor(context,
                                    CGSizeMake(shadowOffset.width, shadowOffset.height),
                                    3.0f,
                                    [UIColor colorWithWhite:0.0f alpha:0.45f].CGColor);
    
    // draw border
    // as circle or square
  
    CGPathRef borderPath = (clipToCircle) ? CGPathCreateWithEllipseInRect(imgRect, NULL) : CGPathCreateWithRect(imgRect, NULL);
    
    CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
    CGContextSetLineWidth(context, borderWidth);
    CGContextAddPath(context, borderPath);
    CGContextDrawPath(context, kCGPathFillStroke);
    CGPathRelease(borderPath);
    CGContextRestoreGState(context);
    
    // clip to circle
    UIBezierPath *imgPath = [UIBezierPath bezierPathWithOvalInRect:imgRect];
    [imgPath addClip];
    
    [self drawInRect:imgRect];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}

- (UIImage *)cutToCorner:(CGFloat)radius
                    size:(CGSize)size
             borderColor:(UIColor *)borderColor
             borderWidth:(CGFloat)borderWidth
            shadowOffSet:(CGSize)shadowOffset
{
    if(CGSizeEqualToSize(size, CGSizeZero))
        size = self.size;
    
    // increase given size for border and shadow
    CGFloat increase = size.width * 0.15f;
    
    CGRect newRect = CGRectMake(0.0f,
                                0.0f,
                                size.width+increase,
                                size.height+increase);
    
    // fit image inside border and shadow
    CGRect imgRect = CGRectMake(increase,
                                increase,
                                newRect.size.width - (increase * 2.0f),
                                newRect.size.height - (increase * 2.0f));
    
    UIGraphicsBeginImageContextWithOptions(newRect.size, NO, [UIScreen mainScreen].scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    
    // draw shadow
    if(!CGSizeEqualToSize(shadowOffset, CGSizeZero))
        CGContextSetShadowWithColor(context,
                                    CGSizeMake(shadowOffset.width, shadowOffset.height),
                                    3.0f,
                                    [UIColor colorWithWhite:0.0f alpha:0.45f].CGColor);
    
    // draw border
    // as circle or square
    CGPathRef borderPath = CGPathCreateWithRoundedRect(imgRect, radius, radius, NULL);
    
    CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
    CGContextSetLineWidth(context, borderWidth);
    CGContextAddPath(context, borderPath);
    CGContextDrawPath(context, kCGPathFillStroke);
    CGPathRelease(borderPath);
    CGContextRestoreGState(context);
    
    UIBezierPath *imgPath = [UIBezierPath bezierPathWithRoundedRect:imgRect cornerRadius:radius];
    [imgPath addClip];
    
    [self drawInRect:imgRect];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}


+ (UIImage *)imageStretchedWithName:(NSString*)imageName capInsets:(UIEdgeInsets)capInsets{
    return [[UIImage imageWithFileName:imageName] resizableImageWithCapInsets:capInsets resizingMode:UIImageResizingModeStretch];
}


+ (CGSize)adaptSizeForImage:(UIImage *)image tagWidth:(CGFloat)tagWidth tagHeight:(CGFloat)tagHeight{
    if(!image){
        return CGSizeMake(tagWidth, tagHeight);
    }
    
    CGSize size = image.size;
    CGFloat width = tagWidth,height=tagHeight;
    // 计算当前image的宽高与要求的比率，以小的一方为基准
    BOOL fixedWith = (tagWidth/size.width)  <  (tagHeight/size.height);
    width = fixedWith ? tagWidth : (tagHeight*size.width/size.height);
    height = fixedWith ? (tagWidth*size.height/size.width) : tagHeight;
    
    return CGSizeMake(width, height);
}





- (UIImage *)imageRotate:(CGFloat)angle {
    CGSize size = self.size;
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    
    //将坐标原点移动至旋转点
    CGContextTranslateCTM(UIGraphicsGetCurrentContext(), size.width/2., size.height/2.);
    //旋转画布
    CGContextRotateCTM(UIGraphicsGetCurrentContext(), angle);
    //还原坐标原点
    CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -size.width/2., -size.height/2.);
    
    [self drawInRect:CGRectMake(0,0,size.width,size.height)];//CGRectMake(size.width * (1 - sqrt(2))/2., size.height * (1 - sqrt(2))/2., size.width * sqrt(2), size.height * sqrt(2))
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}


+ (AFFImageType)imageType:(NSData*)data {
    if (!data) return EImageType_Unknown;
    CFDataRef dataf = (__bridge CFDataRef)data;
    uint64_t length = CFDataGetLength(dataf);
    if (length < 16) return EImageType_Unknown;
    
    const char *bytes = (char *)CFDataGetBytePtr(dataf);
    
    uint32_t magic4 = *((uint32_t *)bytes);
    switch (magic4) {
        case YY_FOUR_CC(0x4D, 0x4D, 0x00, 0x2A): { // big endian TIFF
            return EImageType_TIFF;
        } break;
            
        case YY_FOUR_CC(0x49, 0x49, 0x2A, 0x00): { // little endian TIFF
            return EImageType_TIFF;
        } break;
            
        case YY_FOUR_CC(0x00, 0x00, 0x01, 0x00): { // ICO
            return EImageType_ICO;
        } break;
            
        case YY_FOUR_CC(0x00, 0x00, 0x02, 0x00): { // CUR
            return EImageType_ICO;
        } break;
            
        case YY_FOUR_CC('i', 'c', 'n', 's'): { // ICNS
            return EImageType_ICNS;
        } break;
            
        case YY_FOUR_CC('G', 'I', 'F', '8'): { // GIF
            return EImageType_GIF;
        } break;
            
        case YY_FOUR_CC(0x89, 'P', 'N', 'G'): {  // PNG
            uint32_t tmp = *((uint32_t *)(bytes + 4));
            if (tmp == YY_FOUR_CC('\r', '\n', 0x1A, '\n')) {
                return EImageType_PNG;
            }
        } break;
            
        case YY_FOUR_CC('R', 'I', 'F', 'F'): { // WebP
            uint32_t tmp = *((uint32_t *)(bytes + 8));
            if (tmp == YY_FOUR_CC('W', 'E', 'B', 'P')) {
                return EImageType_WEBP;
            }
        } break;
            
        case YY_FOUR_CC('B', 'P', 'G', 0xFB): {  // BPG
            return EImageType_BPG;
        } break;
            
    }
    
    uint16_t magic2 = *((uint16_t *)bytes);
    switch (magic2) {
        case YY_TWO_CC('B', 'A'):
        case YY_TWO_CC('B', 'M'):
        case YY_TWO_CC('I', 'C'):
        case YY_TWO_CC('P', 'I'):
        case YY_TWO_CC('C', 'I'):
        case YY_TWO_CC('C', 'P'): { // BMP
            return EImageType_BMP;
        }
        case YY_TWO_CC(0xFF, 0x4F): { // JPEG2000
            return EImageType_JPG;
        }
    }
    
    // JPG             FF D8 FF
    if (memcmp(bytes,"\377\330\377",3) == 0) return EImageType_JPG;
    
    // JP2
    if (memcmp(bytes + 4, "\152\120\040\040\015", 5) == 0) return EImageType_JPG;
    
    return EImageType_Unknown;
}

+ (UIImage*)imageNamed:(NSString *)name tintColorStr:(NSString*)tintColorStr {
    return [self imageNamed:name tintColor:[NSString isNilOrEmpty:tintColorStr]?nil:[UIColor colorWithARGBString:tintColorStr]];
}

+ (UIImage*)imageNamed:(NSString *)name tintColor:(UIColor*)tintColor {
    if([NSString isNilOrEmpty:name])return nil;
    UIImage *img = [UIImage imageNamed:name];
    return tintColor?[img imageWithTintColor:tintColor]:img;
}

+ (UIImage *)fixOrientation:(UIImage *)aImage {
    // No-op if the orientation is already correct
    if (aImage.imageOrientation ==UIImageOrientationUp)
        return aImage;
    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    CGAffineTransform transform =CGAffineTransformIdentity;
    switch (aImage.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width,0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }
    switch (aImage.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width,0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.height,0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }
    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx =CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
                                            CGImageGetBitsPerComponent(aImage.CGImage),0,
                                            CGImageGetColorSpace(aImage.CGImage),
                                            CGImageGetBitmapInfo(aImage.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (aImage.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx,CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
            break;
        default:
            CGContextDrawImage(ctx,CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
            break;
    }
    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg =CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}
@end
